home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 4
/
Apprentice-Release4.iso
/
Languages
/
MacQForth 1.0
/
asm6502
/
documentation
/
Assembly in One Step
< prev
Wrap
Text File
|
1995-03-20
|
33KB
|
331 lines
Assembly in one step
--------------------
A brief guide to programming the 6502 in assembly language. It will
introduce the 6502 architecture, addressing modes, and instruction set.
No prior assembly language programming is assumed, however it is assumed
that you are somewhat familiar with hexadecimal numbers. Programming
examples are given at the end. After reading this it is recommended that
you review the file 6502 INSTRUCTION SUMMARY. Much of this material
comes from _6502 Software Design_ by Leo Scanlon, Blacksburg, 1980.
================================================================================
The 6502 Architecture
---------------------
The 6502 is an 8-bit microprocessor that follows the memory oriented
design philosophy of the Motorola 6800. Several engineers left
Motorola and formed MOS Technology which introduced the 6502 in 1975.
The 6502 gained in popularity because of it's low price and became the
heart of several early personal computers including the Apple II,
Commodore 64, and Atari 400 and 800.
Simplicity is key
-----------------
The 6502 handles data in its registers, each of which holds one byte
(8-bits) of data. There are a total of three general use and two special
purpose registers:
accumulator (A) - Handles all arithmetic and logic. The real heart
of the system.
X and Y - General purpose registers with limited abilities.
S - Stack pointer.
P - Processor status. Holds the result of tests
and flags.
All of the 6502 is implemented in MacQForth with the exception of
interrupts and decimal mode arithmetic.
Stack Pointer
-------------
When the microprocessor executes a JSR (Jump to SubRoutine)
instruction it needs to know where to return when finished. The 6502
keeps this information in low memory from $0100 to $01FF and uses the
stack pointer as an offset. The stack grows down from $01FF and makes
it possible to nest subroutines up to 128 levels deep. Not a problem
in most cases.
Processor Status
----------------
The processor status register is not directly accessible by any 6502
instruction. Instead, there exist numerous instructions that test the
bits of the processor status register. The flags within the register
are:
bit -> 7 0
+---+---+---+---+---+---+---+---+
| N | V | | B | D | I | Z | C | <-- flag, 0/1 = reset/set
+---+---+---+---+---+---+---+---+
N = NEGATIVE. Set if bit 7 of the accumulator is set.
V = OVERFLOW. Set if the addition of two like-signed numbers or the
subtraction of two unlike-signed numbers produces a result
greater than +127 or less than -128.
B = BRK COMMAND. Set if an interrupt caused by a BRK, reset if
caused by an external interrupt. Not used in MacQForth.
D = DECIMAL MODE. Set if decimal mode active. Not used in MacQForth.
I = IRQ DISABLE. Set if maskable interrupts are disabled. Not
used in MacQForth.
Z = ZERO. Set if the result of the last operation (load/inc/dec/
add/sub) was zero.
C = CARRY. Set if the add produced a carry, or if the subtraction
produced a borrow. Also holds bits after a logical shift.
Accumulator
-----------
The majority of the 6502's business makes use of the accumulator. All
addition and subtraction is done in the accumulator. It also handles
the majority of the logical comparisons (is A > B ?) and logical bit
shifts.
X and Y
-------
These are index registers often used to hold offsets to memory
locations. They can also be used for holding needed values. Much of
their use lies in supporting some of the addressing modes.
Addressing Modes
----------------
The 6502 has 13 addressing modes, or ways of accessing memory. The 65C02
introduces two additional modes.
They are:
+---------------------+--------------------------+
| mode | assembler format |
+=====================+==========================+
| Immediate | #aa |
| Absolute | aaaa |
| Zero Page | aa | Note:
| Implied | |
| Indirect Absolute | (aaaa) | aa = 2 hex digits
| Absolute Indexed,X | aaaa,X | as $FF
| Absolute Indexed,Y | aaaa,Y |
| Zero Page Indexed,X | aa,X | aaaa = 4 hex
| Zero Page Indexed,Y | aa,Y | digits as
| Indexed Indirect | (aa,X) | $FFFF
| Indirect Indexed | (aa),Y |
| Relative | aaaa | Can also be
| Accumulator | A | assembler labels
+---------------------+--------------------------+
(Table 2-3. _6502 Software Design_, Scanlon, 1980)
Immediate Addressing
--------------------
The value given is a number to be used immediately by the
instruction. For example, LDA #$99 loads the value $99 into the
accumulator.
Absolute Addressing
-------------------
The value given is the address (16-bits) of a memory location that
contains the 8-bit value to be used. For example, STA $3E32 stores
the present value of the accumulator in memory location $3E32.
Zero Page Addressing
-------------- p
-----------------
;
; An 8-bit count down loop
;
start LDX #$FF ; load X with $FF = 255
loop DEX ; X = X - 1
BNE loop ; if X not zero then goto loop
RTS ; return
How does the BNE instruction know that X is zero? It
doesn't, all it knows is that the Z flag is set or reset.
The DEX instruction will set the Z flag when X is zero.
;
; A 16-bit count down loop
;
start LDY #$FF ; load Y with $FF
loop1 LDX #$FF ; load X with $FF
loop2 DEX ; X = X - 1
BNE loop2 ; if X not zero goto loop2
DEY ; Y = Y - 1
BNE loop1 ; if Y not zero goto loop1
RTS ; return
There are two loops here, X will be set to 255 and count to
zero for each time Y is decremented. The net result is to
count the 16-bit number Y (high) and X (low) down from $FFFF
= 65535 to zero.
Other examples
--------------
** Note: All of the following examples are lifted nearly verbatim from
the book "6502 Software Design", whose reference is above.
; Example 4-2. Deleting an entry from an unordered list
;
; Delete the contents of $2F from a list whose starting
; address is in $30 and $31. The first byte of the list
; is its length.
;
deluel LDY #$00 ; fetch element count
LDA ($30),Y
TAX ; transfer length to X
LDA $2F ; item to delete
nextel INY ; index to next element
CMP ($30),Y ; do entry and element match?
BEQ delete ; yes. delete element
DEX ; no. decrement element count
BNE nextel ; any more elements to compare?
RTS ; no. element not in list. done
; delete an element by moving the ones below it up one location
delete DEX ; decrement element count
BEQ deccnt ; end of list?
INY ; no. move next element up
LDA ($30),Y
DEY
STA ($30),Y
INY
JMP delete
deccnt LDA ($30,X) ; update element count of list
SBC #$01
STA ($30,X)
RTS
; Example 5-6. 16-bit by 16-bit unsigned multiply
;
; Multiply $22 (low) and $23 (high) by $20 (low) and
; $21 (high) producing a 32-bit result in $24 (low) to $27 (high)
;
mlt16 LDA #$00 ; clear p2 and p3 of product
STA $26
STA $27
LDX #$16 ; multiplier bit count = 16
nxtbt LSR $21 ; shift two-byte multiplier right
ROR $20
BCC align ; multiplier = 1?
LDA $26 ; yes. fetch p2
CLC
ADC $22 ; and add m0 to it
STA $26 ; store new p2
LDA $27 ; fetch p3
ADC $23 ; and add m1 to it
align ROR A ; rotate four-byte product right
STA $27 ; store new p3
ROR $26
ROR $25
ROR $24
DEX ; decrement bit count
BNE nxtbt ; loop until 16 bits are done
RTS
; Example 5-14. Simple 16-bit square root.
;
; Returns the 8-bit square root in $20 of the
; 16-bit number in $20 (low) and $21 (high). The
; remainder is in location $21.
sqrt16 LDY #$01 ; lsby of first odd number = 1
STY $22
DEY
STY $23 ; msby of first odd number (sqrt = 0)
again SEC
LDA $20 ; save remainder in X register
TAX ; subtract odd lo from integer lo
SBC $22
STA $20
LDA $21 ; subtract odd hi from integer hi
SBC $23
STA $21 ; is subtract result negative?
BCC nomore ; no. increment square root
INY
LDA $22 ; calculate next odd number
ADC #$01
STA $22
BCC again
INC $23
JMP again
nomore STY $20 ; all done, store square root
STX $21 ; and remainder
RTS
This is based on the observation that the square root of an
integer is equal to the number of times an increasing odd
number can be subtracted from the original number and remain
positive. For example,
25
- 1 1
--
24
- 3 2
--
21
- 5 3
--
16
- 7 4
--
9
- 9 5 = square root of 25
--
0
If you are truly interested in learning more, go to your public library
and seek out an Apple machine language programming book. If your public
library is like mine, there will still be plenty of early 80s computer
books on the shelves. :)